// 300：多重选择
// 301：永久移动到新位置
// 302：找到重定向跳转
// 303：参见其他信息
// 304：没有改动
// 305：使用代理
// 307：临时重定向

const http = require('http');
const https = require('https');
const url = require('url'); // 有很多接续 URLs 的方法

// 构造函数被用来创建一个对象来构成请求对象的声明周期
function Request() {
  this.maxRedirects = 10;
  this.redirects = 0;
}

Request.prototype.get = function(href, callback) {
  const uri = url.parse(href); // 解析 URLs 成为 Node http 模块使用的格式，确定是否使用 HTTPS
  const options = { host: uri.host, path: uri.path };
  const httpGet = uri.protocol === 'http:' ? http.get : https.get;

  console.log('GET:', href,uri);

  function processResponse(response) {
    if (response.statusCode >= 300 && response.statusCode < 400) { // 检查状态码是否在 HTTP 重定向范围
      if (this.redirects >= this.maxRedirects) {
        this.error = new Error('Too many redirects for: ' + href);
      } else {
        this.redirects++; // 重定向计数自增
        href = url.resolve(options.host, response.headers.location); // 使用 url.resolve 确保相对路径的 URLs 转换为绝对路径 URLs
        return this.get(href, callback);
      }
    }

    response.url = href;
    response.redirects = this.redirects;

    console.log('Redirected:', href);

    function end() {
      console.log('Connection ended');
      callback(this.error, response);
    }

    response.on('data', function(data) {
      console.log('Got data, length:', data.length);
    });

    response.on('end', end.bind(this)); // 绑定回调到 Request 实例，确保能拿到实例属性
  }

  httpGet(options, processResponse.bind(this))
    .on('error', function(err) {
      callback(err);
    });
};

const request = new Request();
request.get('http://google.com/', function(err, res) {
  if (err) {
    console.error(err);
  } else {
    console.log(`
      Fetched URL: ${res.url} with ${res.redirects} redirects
    `);
    process.exit();
  }
});